/*
PARI/GP scripts related to the eint1,Ei,li,Ci,Si functions
=============================================================
File: LiEiRelatedFunctions.txt
Link: https://oeis.org/wiki/File:LiEiRelatedFunctions.txt
=============================================================
Last updated 12 Nov 2016.
Since PARI supports the exponential integral E_1(z), named
eint1(z), this is used to construct related functions.

Handling of multivalued functions
  log(z), eint1(z), Ei(z), li(z), Ci(z):
The cut is along the negative real axis. Conventionally,
the axis itself is intended congruent with the upper
half-plane C+, implying -Pi < arg(z) <= +Pi.
This is in fact respected for the intrinsic functions
  log(z) and eint1(z). 
In the current update of this file, it has been enforced
and tested also for the functions Ei(z),li(z), and Ci(z).

Note: The functions Si(z) and Cin(z) are entire and thus
present no cut. However, since in this implementation they
depend on non-entire functions, certain care was needed
to ensure continuity in the neighborhood of both axes. 
*/

Ei(z) = {
/* ----------------------------------------------------------
Logarithmic integral function Ei(x) defined for real argument.
The cut along negative real axis is handled as follows:
The real part has no discontinuity and presents no problem.
The imaginary part has a discontinuity and changes from some
positive value just "above" the real axis to its
complex conjugate just "below".
The code was carefully tested for full compatibility in the
whole complex plane with Eric Weisstein's utility on the page
http://mathworld.wolfram.com/ExponentialIntegral.html,
and therefore with Matematica.
Note that at the cut along the negative real axis, the axis
is considered part of the C- half-plane. Thus, for example,
Ei(-1) returns -0.219...-Pi*I (like Ei(-1.0-0.0001*I)),
while Ei(-1.0+0.0001*I) returns -0.219...+Pi*I.
---------------------------------------------------------- */
  my(c=z+0.0*I); \\ If z is real, convert it to complex
  if(imag(c)<0.0, -eint1(-c)-Pi*I, -eint1(-c)+Pi*I);
}

li(z) = {
/* ----------------------------------------------------------
Logarithmic integral function li(z) for any complex argument
except z=1, where its real part diverges to +infinity,
and z=0+0*I, where li(z)=0, which needs a special treatment.
The cut along real axis for x<1 is handled as follows:
The real part has no discontinuity. The imaginary part has a
discontinuity and changes from some positive value just
"above" the real axis to its complex conjugate just "below".
The code was carefully tested for full compatibility in the
whole complex plane with Eric Weisstein's utility on the
page http://mathworld.wolfram.com/LogarithmicIntegral.html,
and therefore with Matematica.
Note of 5 Nov 2016: My original code was simplified
by Charles R. Greathouse (see the history of OEIS A276762).
---------------------------------------------------------- */
  my(c=z+0.0*I); \\ If z is real, convert it to complex
  my(sgn=(-1)^if(real(c)<1,imag(c)<0,imag(c)<=0));
  sgn*Pi*I - eint1(-log(c));
}

Ci(z) = {
/* ----------------------------------------------------------
Cosine integral function Ci(z). The argument may not be 0.
---------------------------------------------------------- */
  my(c=z+0.0*I); \\ If z is real, convert it to complex
  if(abs(c)<Eps_,error("Illegal argument; may not be zero"));
  my(s=-(eint1(c*I)+eint1(-c*I))/2);
  if(imag(c)<0.0,
     if(real(c)>0.0,return(s),return(s-Pi*I)),
     if(real(c)<0.0,return(s+Pi*I),return(s)));
}

Si(z) = {
/* ----------------------------------------------------------
Sine integral function Si(z).
This is an entire function with no cuts.
---------------------------------------------------------- */
  my(c=z+0.0*I); \\ If z is real, convert it to complex
  if(abs(c)<Eps_,return(0.0+0.0*I));
  my(s=abs(real(c))+abs(imag(c))*I);
  s=Pi/2+(eint1(s*I)-eint1(-s*I))/(2*I);
  if(imag(c)<0.0,s=conj(s));  \\ invert imaginary part?
  if(real(c)<0.0,s=conj(-s)); \\ invert real part?
  return(s);
}

Cin(z) = {
/* ----------------------------------------------------------
Entire cosine integral function Cin(z).
This is an entire function with no cuts.
---------------------------------------------------------- */
  return(Euler+log(z)-Ci(z));
}


/*
=============================================================
 Contributed to OEIS Wiki by Stanislav Sykora
=============================================================
*/
